import axios from 'axios'
import { Message, MessageBox, Loading } from 'element-ui' // 根据你的 UI 库调整
// import { getToken, setToken } from '@/utils/auth' // 假设的 token 工具函数
// import { parseTime } from '@/utils' // 假设的时间处理工具

// 1. 创建 Axios 实例 (使用更现代的配置)
const service = axios.create({
    baseURL: process.env.VUE_APP_BASE_API, // 从环境变量读取，便于不同环境切换
    withCredentials: true, // 允许携带 cookies 跨域
    timeout: 10000, // 默认超时 10 秒
    // headers: { // ❌ 不要在这里设置 Content-Type，让 axios 根据 data 自动判断
    //   'Content-Type': 'application/x-www-form-urlencoded'
    // }
})

// 2. 请求拦截器
service.interceptors.request.use(
    config => {
        // a. 添加时间戳 (防缓存)
        if (config.method.toLowerCase() === 'get') {
            config.params = config.params || {}
            config.params['_t'] = Date.now() // 使用 _t 避免与业务参数冲突
        }

        // b. 动态超时 (使用更清晰的命名)
        if (config.custom?.timeout) { // 使用 custom.timeout 避免与 axios 内置 timeout 冲突
            config.timeout = config.custom.timeout
        }

        // c. 添加认证 Token
        /*const token = getToken()
        if (token) {
            // 使用 Bearer Token 是更标准的做法
            config.headers['Authorization'] = 'Bearer ' + token
            // 如果后端要求放在 Cookie，确保 withCredentials: true 即可，无需手动设置 Cookie 头
        }*/

        // d. 【可选】自动设置 Content-Type (推荐)
        // 如果 data 存在且不是 FormData，则根据 data 类型设置
        if (config.data && !(config.data instanceof FormData)) {
            // 如果 data 是对象且没有手动设置 Content-Type
            if (typeof config.data === 'object' && !config.headers['Content-Type']) {
                // 检查是否是表单数据 (简单对象)
                if (isFormDataLike(config.data)) {
                    config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
                    // 【重要】如果使用 application/x-www-form-urlencoded，需要序列化 data
                    config.data = objectToQueryString(config.data)
                } else {
                    // 默认使用 JSON
                    config.headers['Content-Type'] = 'application/json;charset=utf-8'
                    // config.data 保持原样，axios 会自动 JSON.stringify
                }
            }
            // 如果 headers 已经设置了 Content-Type，则尊重手动设置
        }

        // e. 【可选】显示加载动画
        if (config.custom?.showLoading !== false) { // 默认显示，除非显式设置为 false
            config.loadingInstance = Loading.service({ // 将 loading 实例挂载到 config
                lock: true,
                text: '加载中...',
                spinner: 'el-icon-loading',
                background: 'rgba(0, 0, 0, 0.7)'
            })
        }

        return config
    },
    error => {
        console.error('请求拦截器错误:', error)
        return Promise.reject(error)
    }
)

// 3. 响应拦截器
service.interceptors.response.use(
    response => {
        // a. 关闭加载动画 (如果存在)
        if (response.config.loadingInstance) {
            response.config.loadingInstance.close()
        }

        // b. 【关键】处理文件下载
        // 检查 Content-Type 是否为文件类型 (常见 Excel/PDF/Word)
        const contentType = response.headers['content-type'] || ''
        const isFile = /application\/(vnd\.(ms-excel|openxmlformats-officedocument|pdf)|octet-stream)/.test(contentType)
        if (isFile) {
            // 如果是文件，直接返回 response，不进行后续 JSON 解析
            return Promise.resolve(response) // 注意：这里返回的是完整的 response 对象
        }

        // c. 处理 JSON 响应
        // 假设后端返回格式: { code: 200, data: {}, message: '' }
        const res = response.data
        const code = res.code

        // d. 业务成功
        if (code === 200 || code === '200') { // 兼容字符串 '200'
            return res.data // 返回业务数据
        }

        // e. 业务失败 (根据你的后端 code 定义)
        const errorMessage = res.message || '未知错误'

        // f. 特殊状态码处理
        switch (code) {
            case 401: // 未登录/Token 过期
                MessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', {
                    confirmButtonText: '重新登录',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    // 清除本地 Token
                    // setToken('')
                    // 重新加载页面或跳转到登录页
                    location.reload()
                })
                break
            case 403: // 禁止访问
                Message.error('您没有权限执行此操作')
                break
            case 500: // 服务器错误
            case 501:
            case 502:
            case 503:
            case 504:
                Message.error('服务器开小差了，请稍后再试')
                break
            default:
                // 根据 custom 配置决定是否显示错误
                if (response.config.custom?.showErrorMessage !== false) {
                    Message.error(errorMessage)
                }
        }

        // g. 将业务错误也转为 rejected，便于 .catch 捕获
        return Promise.reject(new Error(errorMessage || 'Error'))

        // h. 【可选】检查 Token 刷新
        // const newToken = response.headers['x-new-token'] // 假设后端用此头返回新 Token
        // if (newToken) {
        //   setToken(newToken) // 更新本地 Token
        //   // 注意：这里不能直接修改全局状态，因为拦截器是同步的。更新应发生在业务层或通过 Vuex
        // }

    },
    error => {
        // a. 关闭加载动画 (如果存在)
        if (error.config && error.config.loadingInstance) {
            error.config.loadingInstance.close()
        }

        // b. 处理网络错误/超时
        console.error('响应错误:', error)

        let message = '请求失败'
        if (error.message.includes('timeout')) {
            message = '请求超时，请检查网络'
        } else if (error.message.includes('Network Error')) {
            message = '网络连接失败，请检查网络'
        } else if (error.response) {
            // 服务器返回了错误状态码 (如 404, 500)
            const status = error.response.status
            switch (status) {
                case 404:
                    message = '请求的资源不存在'
                    break
                case 500:
                    message = '服务器内部错误'
                    break
                case 400:
                    message = '请求参数错误'
                    break
                default:
                    message = `请求错误: ${status}`
            }
        } // else: 请求未发出 (如被取消)

        // c. 根据 custom 配置决定是否显示错误
        const showErrorMessage = error.config?.custom?.showErrorMessage
        if (showErrorMessage !== false) { // 默认显示
            Message.error(message)
        }

        // d. 将错误传递下去
        return Promise.reject(error)
    }
)

// 4. 辅助函数
// 判断一个对象是否像表单数据 (简单键值对，无嵌套对象/数组)
function isFormDataLike(obj) {
    return obj && typeof obj === 'object' && !Array.isArray(obj) && Object.values(obj).every(val =>
        val === null ||
        typeof val === 'string' ||
        typeof val === 'number' ||
        typeof val === 'boolean'
    )
}

// 将对象转换为 x-www-form-urlencoded 字符串
function objectToQueryString(obj) {
    return Object.keys(obj)
        .filter(key => obj[key] !== undefined && obj[key] !== null)
        .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)
        .join('&')
}

// 5. 【可选】封装导出，提供更便捷的下载方法
// 专门用于下载文件的实例或方法
const downloadService = axios.create({
    ...service.defaults,
    responseType: 'blob' // 重要：下载必须是 blob
})

// 为 downloadService 添加拦截器 (可以复用或单独定义)
// 这里简单复用，但注意 responseType 已设置
downloadService.interceptors.request.use(config => {
    // 可以在这里为下载请求添加特定逻辑
    config.custom = config.custom || {}
    config.custom.showLoading = config.custom.showLoading !== false // 默认显示
    return config
})

// 导出主服务和下载服务
export default service
export { downloadService }